/*
 * AbstractElements.h
 *
 *  Created on: 2010-9-26
 *      Author: wenjian
 */

#ifndef ABSTRACTELEMENTS_H_
#define ABSTRACTELEMENTS_H_
#include "../commons.h"
#include "eventtypes.h"
#include "ddatatypes.h"
#include "MouseEvent.h"

namespace Ed {
  class AbstractElement;
  class AbstractLayer;

  /**
   * 如果增加、移除或改变了元素位置，大小相关属性，要根据具体情况调用<code>createBoundRect()</code>方法构建矩形边界
   */
  class AbstractElements {
    friend class AbstractElement;
    friend class AbstractLayer;

    public:
      AbstractElements();
      AbstractElements(AbstractElement* e);
      AbstractElements(const std::vector<AbstractElement*>* es);
      virtual ~AbstractElements();

      /**
       * 检查是否为空
       */
      virtual inline bool empty() const{
        return elements.empty();
      }

      /**
       * 返回数量
       */
      virtual inline int size() const{
        return elements.size();
      }

      /**
       * 加入元素
       */
      virtual inline bool add(AbstractElement* e){
        return add(e, elements.size());
      }

      /**
       * 加入元素, 如果元素已经存在，可改变其位置
       */
      virtual bool add(AbstractElement* e, int idx);


      /**
       * 加放多个元素
       */
      virtual inline void addAll(const std::vector<AbstractElement*>* els){
        addAllAndExclude(els, NULL);
      }

      /**
       * 加入除excluded以外的所有元素
       */
      virtual void addAllAndExclude(const std::vector<AbstractElement*>* els, const AbstractElement* excluded=NULL);

      /**
       * 移除元素
       */
      virtual bool remove(AbstractElement* e);

      /**
       * 清除所有元素
       */
      virtual void clear();

      /**
       * 清除除excluded以外的所有元素, 清除时会重画元素
       */
      virtual inline void clearAndExclude(const AbstractElement* excluded=NULL){
        removesAndExclude(NULL, excluded);
      }

      /**
       * 清除除excludeds以外的所有元素, 清除时会重画元素, excludeds中的元素必须是已经被排序过
       */
      virtual inline void clearAndExcludes(const std::vector<AbstractElement*>* excludeds=NULL){
        removesAndExcludes(NULL, excludeds);
      }

      /**
       * 移除参数<code>excluded</code>元素以外的元素, 在v中返回被移除的元素,
       * v可以为NULL
       */
      virtual inline std::vector<AbstractElement*>* removes(vector<AbstractElement*>* excluded=NULL){
        return removesAndExclude(excluded);
      }

      /**
       * 移除参数<code>excluded</code>元素以外的元素, 在v中返回被移除的元素, excluded指示不被移除的元素,
       * v可以为NULL, 即不返回被移除的元素
       */
      virtual std::vector<AbstractElement*>* removesAndExclude(vector<AbstractElement*>* v=NULL, const AbstractElement* excluded=NULL);


      /**
       * 移除参数<code>excludeds</code>元素以外的元素, 在v中返回被移除的元素, excludeds指示不被移除的元素
       * v可以为NULL, 即不返回被移除的元素, excludeds中的元素必须是已经被排序过
       */
      virtual std::vector<AbstractElement*>* removesAndExcludes(vector<AbstractElement*>* v=NULL, const std::vector<AbstractElement*>* excludeds=NULL);


      /**
       * 创建边界矩形
       */
//      virtual void createBoundRect()=0;
      virtual void createBoundRect(){}

      /**
       * 销毁边界矩形
       */
      //virtual void destroyBoundRect()=0;
//      virtual void destroyBoundRect(){}

      /**
       * 检查是否被修改
       */
      virtual bool isModified();

      /**
       * 原地重画与此组里所有元素相交的其它元素, 自己不重画，排除<code>excludeds</code>中的元素
       */
      virtual void redrawIntersection(const std::vector<AbstractElement*>* excludeds=NULL);


      /**
       * 原地重画此组里所有元素, 包括相交元素和自己, 排除<code>excludeds</code>中的元素
       */
      //virtual void redrawAll(const std::vector<AbstractElement*>* excludeds=NULL)=0;
      virtual void redrawAll(const std::vector<AbstractElement*>* excludeds=NULL){}


      /**
       * 增量移动到目标位置
       */
      virtual void moveBy(real dx, real dy);


      /**
       * 返回元素索引位置, 如果元素不存在，返回-1
       */
      virtual int getIndex(AbstractElement* e);

      /**
       * 返回元素索引位置, 如果元素不存在，返回 elements.end()
       */
      virtual std::vector<AbstractElement*>::iterator getPosition (AbstractElement* e);

      /**
       * 返回所有元素
       */
      virtual inline const std::vector<AbstractElement*>* getAbstractElements() const{
        return &elements;
      }

      /**
       * 检查是否包含此元素
       */
      virtual bool contains(const AbstractElement* e) const;


      /**
       * 对元素进行排序
       */
      virtual void sort();

      /**
       * 返回鼠标事件响应元素
       */
      virtual inline AbstractElement* getMouseHoveringElement() const{
        return mouseHoveringElement;
      }

      /**
       * 检查是否允许响应事件
       */
      //virtual bool isEventEnabled()=0;
      virtual bool isEventEnabled(){return false;}

      /**
       * 返回图层
       */
      //virtual AbstractLayer* getLayer()=0;
      virtual AbstractLayer* getLayer(){return NULL;}

      /**
       * 设置图层
       */
      virtual void setLayer(AbstractLayer* l){}


      /**
       * 跟踪响应事件
       */
      //virtual bool trackEvent(const Thk::Event* e)=0;
      virtual bool trackEvent(const Thk::Event* e){return false;};

      /**
       * 交换元素位置
       */
      virtual void swap(int lIdx, int rIdx);

    protected:
      /**
       * 发送鼠标离开事件
       */
      //virtual bool mouseLeave()=0;
//      virtual bool mouseLeave(){return false;}

//    private:
    protected:
      /**
       * 处理鼠标事件
       */
      virtual bool handleMouseEvent(const MouseEvent* me);


      /**
       * 返回指定坐标 x,y上的最顶层可视并能响应事件的元素, 如果没有，返回NULL
       *
       * @param x X坐标
       * @param y Y坐标
       * @param excluded 被排除的元素
       *
       */
      AbstractElement* findByEventEnabled(real x, real y, const AbstractElement* excluded = NULL);

      /**
       * 鼠标离开元素
       */
      void mouseLeaveElement(AbstractElement* e);

      /**
       * 设置排序标记
       */
      inline void setSortFlag(bool b){
        sortFlag = b;
      }
      /**
       * 检查是否已经被排过序
       */
      inline bool isSorted() const{
        return sortFlag;
      }

      /**
       * 移除元素
       */
      void remove(std::vector<AbstractElement*>::iterator it);

    protected:
      //定义所有元素
      typedef std::vector<AbstractElement*> VElements;
      typedef std::pair<VElements::iterator, VElements::iterator> VElementsIteratorPair;
      //所有元素
      VElements elements;
      //已经被排序标记
      bool sortFlag;
      //鼠标事件响应元素
      AbstractElement* mouseHoveringElement;
  };

}

#endif /* ABSTRACTELEMENTS_H_ */
